package com.bob.clan.wxconnector.component;

import com.bob.clan.wxconnector.DTO.WxMsgDTO;
import com.bob.clan.wxconnector.DTO.WxMsgLow;
import com.bob.clan.wxconnector.entity.WxMsg;
import org.springframework.stereotype.Component;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class WxMsgComponent {
    public <T> T map2Msg(HashMap<String, Object> map, Class<T> clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        T msg = clazz.getDeclaredConstructor().newInstance();
        for(Map.Entry<String,Object> entry: map.entrySet()){
            Field field = clazz.getDeclaredField(entry.getKey());
            field.setAccessible(true);
            field.set(msg, entry.getValue());
        }
        return msg;
    }

    public <T> T xml2Msg(String xml,Class<T> clazz) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        StringReader reader = new StringReader(xml);
        return (T) jaxbUnmarshaller.unmarshal(reader);
    }

    public String msg2Xml(WxMsgDTO msg) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(WxMsgDTO.class);
        Marshaller marshaller = context.createMarshaller();

        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);//AXB_FRAGMENT属性为true来实现。这样，JAXB将不会生成XML声明和根元素
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        StringWriter sw = new StringWriter();
        marshaller.marshal(msg, sw);
        return sw.toString();
    }

    public String msg2Xml(WxMsgLow msg) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(WxMsgDTO.class);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        StringWriter sw = new StringWriter();
        marshaller.marshal(msg, sw);
        return sw.toString();
    }

    public WxMsg dto2Msg(WxMsgDTO msgDTO) throws IllegalAccessException {
        WxMsg wxMsg = new WxMsg();
        copyProperties(msgDTO, wxMsg);//相同属性直接复制
        //有5个属性需要单独处理
        wxMsg.setLocationY(msgDTO.getLocation_Y());
        wxMsg.setLocationX(msgDTO.getLocation_X());
        wxMsg.setLocationPrecision(msgDTO.getPrecision());
        wxMsg.setMediaId16k(msgDTO.getMediaId16K());
        wxMsg.setInsertTime(new Date(msgDTO.getCreateTime() * 1000));
        return wxMsg;
    }

    public WxMsgDTO msg2DTO(WxMsg msg) throws IllegalAccessException {
        WxMsgDTO msgDTO = new WxMsgDTO();
        copyProperties(msg, msgDTO);//相同属性直接复制
        //有4个属性需要单独处理
        msgDTO.setLocation_X(msg.getLocationX());
        msgDTO.setLocation_Y(msg.getLocationY());
        msgDTO.setPrecision(msg.getLocationPrecision());
        msgDTO.setMediaId16K(msg.getMediaId16k());
        return msgDTO;
    }

    private void copyProperties(Object source, Object target) throws IllegalAccessException {
        Field[] sourceFields = source.getClass().getDeclaredFields();
        Field[] targetFields = target.getClass().getDeclaredFields();

        for (Field sourceField : sourceFields) {
            sourceField.setAccessible(true); // 允许访问私有字段
            for (Field targetField : targetFields) {
                targetField.setAccessible(true); // 允许访问私有字段
                if (sourceField.getName().equals(targetField.getName()) &&
                        sourceField.getType().equals(targetField.getType())) {
                    // 如果属性名称和类型都相同，则复制值
                    targetField.set(target, sourceField.get(source));
                }
            }
        }
    }
}
